﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.IO;
using lucere.analysis;

namespace lucere.entity
{
    /// <summary>
    /// <para>Synonymous with IField</para>
    /// <para>
    /// WARNING: This interface may change within minor versions, despite Lucene's backward compatibility requirements.
    /// This means new methods may be added from version to version.  This change only affects the Fieldable API; other backwards
    /// compatibility promises remain intact. For example, Lucene can still
    /// read and write indices created within the same major version.
    /// </para>
    /// </summary>
    public interface IFieldable : ISerializable
    {
        /// <summary>
        /// <para>
        /// Gets/Sets the boost factor hits on this field.  This value will be
        /// multiplied into the score of all hits on this this field of this
        /// document.
        /// 
        /// <para/>
        /// The boost is multiplied by {@link Lucene.Net.Documents.Document#GetBoost()} of the document
        /// containing this field.  If a document has multiple fields with the same
        /// name, all such values are multiplied together.  This product is then
        /// used to compute the norm factor for the field.  By
        /// default, in the {@link
        /// Lucene.Net.Search.Similarity#ComputeNorm(String,
        /// FieldInvertState)} method, the boost value is multiplied
        /// by the {@link
        /// Lucene.Net.Search.Similarity#LengthNorm(String,
        /// int)} and then rounded by {@link Lucene.Net.Search.Similarity#EncodeNorm(float)} before it is stored in the
        /// index.  One should attempt to ensure that this product does not overflow
        /// the range of that encoding.
        /// </summary>
        float Boost { get; set; }
        /// <summary>Returns the name of the field as an interned string.
        /// For example "date", "title", "body", ...
        /// </summary>
        string Name { get; }

        /// <summary>True if the value of the field is to be stored in the index for return
        /// with search hits. 
        /// </summary>
        bool IsStored { get; }
        /// <summary>True if the value of the field is to be indexed, so that it may be
        /// searched on. 
        /// </summary>
        bool IsIndexed { get; }
        /// <summary>True if the value of the field should be tokenized as text prior to
        /// indexing.  Un-tokenized fields are indexed as a single word and may not be
        /// Reader-valued. 
        /// </summary>
        bool IsTokenized { get; }
        /// <summary>True if the value of the field is stored as binary </summary>
        bool IsBinary { get; }
        /// <summary> Indicates whether a Field is Lazy or not.  The semantics of Lazy loading are such that if a Field is lazily loaded, retrieving
        /// it's values via {@link #StringValue()} or {@link #BinaryValue()} is only valid as long as the {@link Lucene.Net.Index.IndexReader} that
        /// retrieved the {@link Document} is still open.
        /// </summary>
        bool IsLazy { get; }

        /// <summary>True if the term or terms used to index this field are stored as a term
        /// vector, available from {@link Lucene.Net.Index.IndexReader#GetTermFreqVector(int,String)}.
        /// These methods do not provide access to the original content of the field,
        /// only to terms used to index it. If the original content must be
        /// preserved, use the <code>stored</code> attribute instead.
        /// 
        /// </summary>
        bool IsTermVectorStored { get; }
        /// <summary> True if terms are stored as term vector together with their offsets 
        /// (start and end positon in source text).
        /// </summary>
        bool IsStoreOffsetWithTermVector { get; }
        /// <summary> True if terms are stored as term vector together with their token positions.</summary>
        bool IsStorePositionWithTermVector { get; }
        /// <summary>
        /// True if norms are omitted for this indexed field 
        /// If set, omit normalization factors associated with this indexed field.
        /// This effectively disables indexing boosts and length normalization for this field.
        /// </summary>
        bool OmitNorms { get; set; }
        /// <summary> Returns offset into byte[] segment that is used as value, if Field is not binary
        /// returned value is undefined
        /// </summary>
        int BinaryOffset { get; }
        /// <summary> Returns length of byte[] segment that is used as value, if Field is not binary
        /// returned value is undefined
        /// </summary>
        int BinaryLength { get; }

        /// <summary>The value of the field as a String, or null.
        /// <p/>
        /// For indexing, if isStored()==true, the stringValue() will be used as the stored field value
        /// unless isBinary()==true, in which case binaryValue() will be used.
        /// 
        /// If isIndexed()==true and isTokenized()==false, this String value will be indexed as a single token.
        /// If isIndexed()==true and isTokenized()==true, then tokenStreamValue() will be used to generate indexed tokens if not null,
        /// else readerValue() will be used to generate indexed tokens if not null, else stringValue() will be used to generate tokens.
        /// </summary>
        string StringValue { get; }
        /// <summary>The value of the field as a Reader, which can be used at index time to generate indexed tokens.</summary>
        TextReader ReaderValue { get; }
        /// <summary>The TokenStream for this field to be used when indexing, or null.</summary>
        ITokenStream TokenStreamValue { get; }
        /// <summary>The value of the field in Binary, or null.</summary>
        byte[] BinaryValue { get; }
        /// <summary> Return the raw byte[] for the binary field.  Note that
        /// you must also call {@link #getBinaryLength} and {@link
        /// #getBinaryOffset} to know which range of bytes in this
        /// returned array belong to the field.
        /// </summary>
        byte[] GetBinaryValue();
        /// <summary> Return the raw byte[] for the binary field.  Note that
        /// you must also call {@link #getBinaryLength} and {@link
        /// #getBinaryOffset} to know which range of bytes in this
        /// returned array belong to the field.<p/>
        /// About reuse: if you pass in the result byte[] and it is
        /// used, likely the underlying implementation will hold
        /// onto this byte[] and return it in future calls to
        /// {@link #BinaryValue()} or {@link #GetBinaryValue()}.
        /// So if you subsequently re-use the same byte[] elsewhere
        /// it will alter this Fieldable's value.
        /// </summary>
        /// <param name="paramArrayOfByte"> User defined buffer that will be used if
        /// possible.  If this is null or not large enough, a new
        /// buffer is allocated
        /// </param>
        byte[] GetBinaryValue(byte[] paramArrayOfByte);

        bool OmitTermFreqAndPositions { get; set; }
    }
}
